<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">


<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    
    <title>11. 标准库浏览 – Part II &mdash; Python tutorial 3.4 documentation</title>
    
    <link rel="stylesheet" href="_static/default.css" type="text/css" />
    <link rel="stylesheet" href="_static/pygments.css" type="text/css" />
    
    <script type="text/javascript">
      var DOCUMENTATION_OPTIONS = {
        URL_ROOT:    './',
        VERSION:     '3.4',
        COLLAPSE_INDEX: false,
        FILE_SUFFIX: '.html',
        HAS_SOURCE:  true
      };
    </script>
    <script type="text/javascript" src="_static/jquery.js"></script>
    <script type="text/javascript" src="_static/underscore.js"></script>
    <script type="text/javascript" src="_static/doctools.js"></script>
    <link rel="top" title="Python tutorial 3.4 documentation" href="index.html" />
    <link rel="next" title="12. 接下来？" href="whatnow.html" />
    <link rel="prev" title="10. Python 标准库概览" href="stdlib.html" /> 
  </head>
  <body>
    <div class="related">
      <h3>Navigation</h3>
      <ul>
        <li class="right" style="margin-right: 10px">
          <a href="genindex.html" title="General Index"
             accesskey="I">index</a></li>
        <li class="right" >
          <a href="whatnow.html" title="12. 接下来？"
             accesskey="N">next</a> |</li>
        <li class="right" >
          <a href="stdlib.html" title="10. Python 标准库概览"
             accesskey="P">previous</a> |</li>
        <li><a href="index.html">Python tutorial 3.4 documentation</a> &raquo;</li> 
      </ul>
    </div>  

    <div class="document">
      <div class="documentwrapper">
        <div class="bodywrapper">
          <div class="body">
            
  <div class="section" id="part-ii">
<span id="tut-brieftourtwo"></span><h1>11. 标准库浏览 &#8211; Part II<a class="headerlink" href="#part-ii" title="Permalink to this headline">¶</a></h1>
<p>第二部分包含了支持专业编程工作所需的更高级的模块，这些模块很少出现在小脚本中。</p>
<div class="section" id="tut-output-formatting">
<span id="id1"></span><h2>11.1. 输出格式<a class="headerlink" href="#tut-output-formatting" title="Permalink to this headline">¶</a></h2>
<p><tt class="xref py py-mod docutils literal"><span class="pre">reprlib</span></tt> 模块为大型的或深度嵌套的容器缩写显示提供了 <tt class="xref py py-func docutils literal"><span class="pre">repr()</span></tt> 函数的一个定制版本:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span> <span class="nn">reprlib</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">reprlib</span><span class="o">.</span><span class="n">repr</span><span class="p">(</span><span class="nb">set</span><span class="p">(</span><span class="s">&#39;supercalifragilisticexpialidocious&#39;</span><span class="p">))</span>
<span class="go">&quot;set([&#39;a&#39;, &#39;c&#39;, &#39;d&#39;, &#39;e&#39;, &#39;f&#39;, &#39;g&#39;, ...])&quot;</span>
</pre></div>
</div>
<p><tt class="xref py py-mod docutils literal"><span class="pre">pprint</span></tt> 模块给老手提供了一种解释器可读的方式深入控制内置和用户自定义对象的打印。当输出超过一行的时候，“美化打印（pretty printer）”添加断行和标识符，使得数据结构显示的更清晰:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span> <span class="nn">pprint</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">t</span> <span class="o">=</span> <span class="p">[[[[</span><span class="s">&#39;black&#39;</span><span class="p">,</span> <span class="s">&#39;cyan&#39;</span><span class="p">],</span> <span class="s">&#39;white&#39;</span><span class="p">,</span> <span class="p">[</span><span class="s">&#39;green&#39;</span><span class="p">,</span> <span class="s">&#39;red&#39;</span><span class="p">]],</span> <span class="p">[[</span><span class="s">&#39;magenta&#39;</span><span class="p">,</span>
<span class="gp">... </span>    <span class="s">&#39;yellow&#39;</span><span class="p">],</span> <span class="s">&#39;blue&#39;</span><span class="p">]]]</span>
<span class="gp">...</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">pprint</span><span class="o">.</span><span class="n">pprint</span><span class="p">(</span><span class="n">t</span><span class="p">,</span> <span class="n">width</span><span class="o">=</span><span class="mi">30</span><span class="p">)</span>
<span class="go">[[[[&#39;black&#39;, &#39;cyan&#39;],</span>
<span class="go">   &#39;white&#39;,</span>
<span class="go">   [&#39;green&#39;, &#39;red&#39;]],</span>
<span class="go">  [[&#39;magenta&#39;, &#39;yellow&#39;],</span>
<span class="go">   &#39;blue&#39;]]]</span>
</pre></div>
</div>
<p><tt class="xref py py-mod docutils literal"><span class="pre">textwrap</span></tt> 模块格式化文本段落以适应设定的屏宽:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span> <span class="nn">textwrap</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">doc</span> <span class="o">=</span> <span class="s">&quot;&quot;&quot;The wrap() method is just like fill() except that it returns</span>
<span class="gp">... </span><span class="s">a list of strings instead of one big string with newlines to separate</span>
<span class="gp">... </span><span class="s">the wrapped lines.&quot;&quot;&quot;</span>
<span class="gp">...</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">print</span><span class="p">(</span><span class="n">textwrap</span><span class="o">.</span><span class="n">fill</span><span class="p">(</span><span class="n">doc</span><span class="p">,</span> <span class="n">width</span><span class="o">=</span><span class="mi">40</span><span class="p">))</span>
<span class="go">The wrap() method is just like fill()</span>
<span class="go">except that it returns a list of strings</span>
<span class="go">instead of one big string with newlines</span>
<span class="go">to separate the wrapped lines.</span>
</pre></div>
</div>
<p><tt class="xref py py-mod docutils literal"><span class="pre">locale</span></tt> 模块按访问预定好的国家信息数据库。locale 的格式化函数属性集提供了一个直接方式以分组标示格式化数字:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span> <span class="nn">locale</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">locale</span><span class="o">.</span><span class="n">setlocale</span><span class="p">(</span><span class="n">locale</span><span class="o">.</span><span class="n">LC_ALL</span><span class="p">,</span> <span class="s">&#39;English_United States.1252&#39;</span><span class="p">)</span>
<span class="go">&#39;English_United States.1252&#39;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">conv</span> <span class="o">=</span> <span class="n">locale</span><span class="o">.</span><span class="n">localeconv</span><span class="p">()</span>          <span class="c"># get a mapping of conventions</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">x</span> <span class="o">=</span> <span class="mf">1234567.8</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">locale</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="s">&quot;</span><span class="si">%d</span><span class="s">&quot;</span><span class="p">,</span> <span class="n">x</span><span class="p">,</span> <span class="n">grouping</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
<span class="go">&#39;1,234,567&#39;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">locale</span><span class="o">.</span><span class="n">format_string</span><span class="p">(</span><span class="s">&quot;</span><span class="si">%s%.*f</span><span class="s">&quot;</span><span class="p">,</span> <span class="p">(</span><span class="n">conv</span><span class="p">[</span><span class="s">&#39;currency_symbol&#39;</span><span class="p">],</span>
<span class="gp">... </span>                     <span class="n">conv</span><span class="p">[</span><span class="s">&#39;frac_digits&#39;</span><span class="p">],</span> <span class="n">x</span><span class="p">),</span> <span class="n">grouping</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
<span class="go">&#39;$1,234,567.80&#39;</span>
</pre></div>
</div>
</div>
<div class="section" id="tut-templating">
<span id="id2"></span><h2>11.2. 模板<a class="headerlink" href="#tut-templating" title="Permalink to this headline">¶</a></h2>
<p><tt class="xref py py-mod docutils literal"><span class="pre">string</span></tt> 提供了一个灵活多变的模版类 <tt class="xref py py-class docutils literal"><span class="pre">Template</span></tt> ，使用它最终用户可以用简单的进行编辑。这使用户可以在不进行改变的情况下定制他们的应用程序。</p>
<p>格式使用 <tt class="docutils literal"><span class="pre">$</span></tt> 为开头的 Python 合法标识（数字、字母和下划线）作为占位符。占位符外面的大括号使它可以和其它的字符不加空格混在一起。 <tt class="docutils literal"><span class="pre">$$</span></tt> 创建一个单独的 <tt class="docutils literal"><span class="pre">$</span></tt>:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">string</span> <span class="kn">import</span> <span class="n">Template</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">t</span> <span class="o">=</span> <span class="n">Template</span><span class="p">(</span><span class="s">&#39;${village}folk send $$10 to $cause.&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">t</span><span class="o">.</span><span class="n">substitute</span><span class="p">(</span><span class="n">village</span><span class="o">=</span><span class="s">&#39;Nottingham&#39;</span><span class="p">,</span> <span class="n">cause</span><span class="o">=</span><span class="s">&#39;the ditch fund&#39;</span><span class="p">)</span>
<span class="go">&#39;Nottinghamfolk send $10 to the ditch fund.&#39;</span>
</pre></div>
</div>
<p>当一个占位符在字典或关键字参数中没有被提供时， <tt class="xref py py-meth docutils literal"><span class="pre">substitute()</span></tt> 方法就会抛出一个 <tt class="xref py py-exc docutils literal"><span class="pre">KeyError</span></tt> 异常。 对于邮件合并风格的应用程序，用户提供的数据可能并不完整，这时使用 <tt class="xref py py-meth docutils literal"><span class="pre">safe_substitute()</span></tt> 方法可能更适合 — 如果数据不完整，它就不会改变占位符:</p>
<div class="highlight-python"><div class="highlight"><pre>&gt;&gt;&gt; t = Template(&#39;Return the $item to $owner.&#39;)
&gt;&gt;&gt; d = dict(item=&#39;unladen swallow&#39;)
&gt;&gt;&gt; t.substitute(d)
Traceback (most recent call last):
  . . .
KeyError: &#39;owner&#39;
&gt;&gt;&gt; t.safe_substitute(d)
&#39;Return the unladen swallow to $owner.&#39;
</pre></div>
</div>
<p>模板子类可以指定一个自定义分隔符。 例如，图像查看器的批量重命名工具可能选择使用百分号作为占位符，像当前日期，图片序列号或文件格式:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span> <span class="nn">time</span><span class="o">,</span> <span class="nn">os.path</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">photofiles</span> <span class="o">=</span> <span class="p">[</span><span class="s">&#39;img_1074.jpg&#39;</span><span class="p">,</span> <span class="s">&#39;img_1076.jpg&#39;</span><span class="p">,</span> <span class="s">&#39;img_1077.jpg&#39;</span><span class="p">]</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">class</span> <span class="nc">BatchRename</span><span class="p">(</span><span class="n">Template</span><span class="p">):</span>
<span class="gp">... </span>    <span class="n">delimiter</span> <span class="o">=</span> <span class="s">&#39;%&#39;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">fmt</span> <span class="o">=</span> <span class="nb">input</span><span class="p">(</span><span class="s">&#39;Enter rename style (</span><span class="si">%d</span><span class="s">-date %n-seqnum </span><span class="si">%f</span><span class="s">-format):  &#39;</span><span class="p">)</span>
<span class="go">Enter rename style (%d-date %n-seqnum %f-format):  Ashley_%n%f</span>

<span class="gp">&gt;&gt;&gt; </span><span class="n">t</span> <span class="o">=</span> <span class="n">BatchRename</span><span class="p">(</span><span class="n">fmt</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">date</span> <span class="o">=</span> <span class="n">time</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="s">&#39;</span><span class="si">%d</span><span class="s">%b%y&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">filename</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">photofiles</span><span class="p">):</span>
<span class="gp">... </span>    <span class="n">base</span><span class="p">,</span> <span class="n">ext</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">splitext</span><span class="p">(</span><span class="n">filename</span><span class="p">)</span>
<span class="gp">... </span>    <span class="n">newname</span> <span class="o">=</span> <span class="n">t</span><span class="o">.</span><span class="n">substitute</span><span class="p">(</span><span class="n">d</span><span class="o">=</span><span class="n">date</span><span class="p">,</span> <span class="n">n</span><span class="o">=</span><span class="n">i</span><span class="p">,</span> <span class="n">f</span><span class="o">=</span><span class="n">ext</span><span class="p">)</span>
<span class="gp">... </span>    <span class="k">print</span><span class="p">(</span><span class="s">&#39;{0} --&gt; {1}&#39;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">filename</span><span class="p">,</span> <span class="n">newname</span><span class="p">))</span>

<span class="go">img_1074.jpg --&gt; Ashley_0.jpg</span>
<span class="go">img_1076.jpg --&gt; Ashley_1.jpg</span>
<span class="go">img_1077.jpg --&gt; Ashley_2.jpg</span>
</pre></div>
</div>
<p>模板的另一个应用是把多样的输出格式细节从程序逻辑中分类出来。这便使得XML文件，纯文本报表和HTML WEB报表定制模板成为可能。</p>
</div>
<div class="section" id="tut-binary-formats">
<span id="id3"></span><h2>11.3. 使用二进制数据记录布局<a class="headerlink" href="#tut-binary-formats" title="Permalink to this headline">¶</a></h2>
<p><tt class="xref py py-mod docutils literal"><span class="pre">struct</span></tt> 模块为使用变长的二进制记录格式提供了 <tt class="xref py py-func docutils literal"><span class="pre">pack()</span></tt> 和 <tt class="xref py py-func docutils literal"><span class="pre">unpack()</span></tt> 函数。 下面的示例演示了在不使用 <tt class="xref py py-mod docutils literal"><span class="pre">zipfile</span></tt> 模块的情况下如何迭代一个 ZIP 文件的头信息。 压缩码 <tt class="docutils literal"><span class="pre">&quot;H&quot;</span></tt> 和 <tt class="docutils literal"><span class="pre">&quot;I&quot;</span></tt> 分别表示2和4字节无符号数字， <tt class="docutils literal"><span class="pre">&quot;&lt;&quot;</span></tt> 表明它们都是标准大小并且按照 little-endian 字节排序。</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">struct</span>

<span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="s">&#39;myfile.zip&#39;</span><span class="p">,</span> <span class="s">&#39;rb&#39;</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
    <span class="n">data</span> <span class="o">=</span> <span class="n">f</span><span class="o">.</span><span class="n">read</span><span class="p">()</span>

<span class="n">start</span> <span class="o">=</span> <span class="mi">0</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">3</span><span class="p">):</span>                      <span class="c"># show the first 3 file headers</span>
    <span class="n">start</span> <span class="o">+=</span> <span class="mi">14</span>
    <span class="n">fields</span> <span class="o">=</span> <span class="n">struct</span><span class="o">.</span><span class="n">unpack</span><span class="p">(</span><span class="s">&#39;&lt;IIIHH&#39;</span><span class="p">,</span> <span class="n">data</span><span class="p">[</span><span class="n">start</span><span class="p">:</span><span class="n">start</span><span class="o">+</span><span class="mi">16</span><span class="p">])</span>
    <span class="n">crc32</span><span class="p">,</span> <span class="n">comp_size</span><span class="p">,</span> <span class="n">uncomp_size</span><span class="p">,</span> <span class="n">filenamesize</span><span class="p">,</span> <span class="n">extra_size</span> <span class="o">=</span> <span class="n">fields</span>

    <span class="n">start</span> <span class="o">+=</span> <span class="mi">16</span>
    <span class="n">filename</span> <span class="o">=</span> <span class="n">data</span><span class="p">[</span><span class="n">start</span><span class="p">:</span><span class="n">start</span><span class="o">+</span><span class="n">filenamesize</span><span class="p">]</span>
    <span class="n">start</span> <span class="o">+=</span> <span class="n">filenamesize</span>
    <span class="n">extra</span> <span class="o">=</span> <span class="n">data</span><span class="p">[</span><span class="n">start</span><span class="p">:</span><span class="n">start</span><span class="o">+</span><span class="n">extra_size</span><span class="p">]</span>
    <span class="k">print</span><span class="p">(</span><span class="n">filename</span><span class="p">,</span> <span class="nb">hex</span><span class="p">(</span><span class="n">crc32</span><span class="p">),</span> <span class="n">comp_size</span><span class="p">,</span> <span class="n">uncomp_size</span><span class="p">)</span>

    <span class="n">start</span> <span class="o">+=</span> <span class="n">extra_size</span> <span class="o">+</span> <span class="n">comp_size</span>     <span class="c"># skip to the next header</span>
</pre></div>
</div>
</div>
<div class="section" id="tut-multi-threading">
<span id="id4"></span><h2>11.4. 多线程<a class="headerlink" href="#tut-multi-threading" title="Permalink to this headline">¶</a></h2>
<p>线程是一个分离无顺序依赖关系任务的技术。在某些任务运行于后台的时候应用程序会变得迟缓，线程可以提升其速度。一个有关的用途是在 I/O 的同时其它线程可以并行计算。</p>
<p>下面的代码显示了高级模块 <tt class="xref py py-mod docutils literal"><span class="pre">threading</span></tt> 如何在主程序运行的同时运行任务:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">threading</span><span class="o">,</span> <span class="nn">zipfile</span>

<span class="k">class</span> <span class="nc">AsyncZip</span><span class="p">(</span><span class="n">threading</span><span class="o">.</span><span class="n">Thread</span><span class="p">):</span>
    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">infile</span><span class="p">,</span> <span class="n">outfile</span><span class="p">):</span>
        <span class="n">threading</span><span class="o">.</span><span class="n">Thread</span><span class="o">.</span><span class="n">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">infile</span> <span class="o">=</span> <span class="n">infile</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">outfile</span> <span class="o">=</span> <span class="n">outfile</span>
    <span class="k">def</span> <span class="nf">run</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="n">f</span> <span class="o">=</span> <span class="n">zipfile</span><span class="o">.</span><span class="n">ZipFile</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">outfile</span><span class="p">,</span> <span class="s">&#39;w&#39;</span><span class="p">,</span> <span class="n">zipfile</span><span class="o">.</span><span class="n">ZIP_DEFLATED</span><span class="p">)</span>
        <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">infile</span><span class="p">)</span>
        <span class="n">f</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
        <span class="k">print</span><span class="p">(</span><span class="s">&#39;Finished background zip of:&#39;</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">infile</span><span class="p">)</span>

<span class="n">background</span> <span class="o">=</span> <span class="n">AsyncZip</span><span class="p">(</span><span class="s">&#39;mydata.txt&#39;</span><span class="p">,</span> <span class="s">&#39;myarchive.zip&#39;</span><span class="p">)</span>
<span class="n">background</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>
<span class="k">print</span><span class="p">(</span><span class="s">&#39;The main program continues to run in foreground.&#39;</span><span class="p">)</span>

<span class="n">background</span><span class="o">.</span><span class="n">join</span><span class="p">()</span>    <span class="c"># Wait for the background task to finish</span>
<span class="k">print</span><span class="p">(</span><span class="s">&#39;Main program waited until background was done.&#39;</span><span class="p">)</span>
</pre></div>
</div>
<p>多线程应用程序的主要挑战是协调线程，诸如线程间共享数据或其它资源。 为了达到那个目的，线程模块提供了许多同步化的原生支持，包括：锁，事件，条件变量和信号灯。</p>
<p>尽管这些工具很强大，微小的设计错误也可能造成难以挽回的故障。 因此，任务协调的首选方法是把对一个资源的所有访问集中在一个单独的线程中，然后使用 <tt class="xref py py-mod docutils literal"><span class="pre">queue</span></tt> 模块用那个线程服务其他线程的请求。 为内部线程通信和协调而使用 <tt class="xref py py-class docutils literal"><span class="pre">Queue</span></tt> 对象的应用程序更易于设计，更可读，并且更可靠。</p>
</div>
<div class="section" id="tut-logging">
<span id="id5"></span><h2>11.5. 日志<a class="headerlink" href="#tut-logging" title="Permalink to this headline">¶</a></h2>
<p><tt class="xref py py-mod docutils literal"><span class="pre">logging</span></tt> 模块提供了完整和灵活的日志系统。它最简单的用法是记录信息并发送到一个文件或 <tt class="docutils literal"><span class="pre">sys.stderr</span></tt>:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">logging</span>
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s">&#39;Debugging information&#39;</span><span class="p">)</span>
<span class="n">logging</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="s">&#39;Informational message&#39;</span><span class="p">)</span>
<span class="n">logging</span><span class="o">.</span><span class="n">warning</span><span class="p">(</span><span class="s">&#39;Warning:config file </span><span class="si">%s</span><span class="s"> not found&#39;</span><span class="p">,</span> <span class="s">&#39;server.conf&#39;</span><span class="p">)</span>
<span class="n">logging</span><span class="o">.</span><span class="n">error</span><span class="p">(</span><span class="s">&#39;Error occurred&#39;</span><span class="p">)</span>
<span class="n">logging</span><span class="o">.</span><span class="n">critical</span><span class="p">(</span><span class="s">&#39;Critical error -- shutting down&#39;</span><span class="p">)</span>
</pre></div>
</div>
<p>输出如下:</p>
<div class="highlight-python"><div class="highlight"><pre>WARNING:root:Warning:config file server.conf not found
ERROR:root:Error occurred
CRITICAL:root:Critical error -- shutting down
</pre></div>
</div>
<p>默认情况下捕获信息和调试消息并将输出发送到标准错误流。其它可选的路由信息方式通过 email，数据报文，socket 或者 HTTP Server。基于消息属性，新的过滤器可以选择不同的路由： <tt class="xref py py-const docutils literal"><span class="pre">DEBUG</span></tt>, <tt class="xref py py-const docutils literal"><span class="pre">INFO</span></tt>,
<tt class="xref py py-const docutils literal"><span class="pre">WARNING</span></tt>, <tt class="xref py py-const docutils literal"><span class="pre">ERROR</span></tt>, 和 <tt class="xref py py-const docutils literal"><span class="pre">CRITICAL</span></tt> 。</p>
<p>日志系统可以直接在 Python 代码中定制，也可以不经过应用程序直接在一个用户可编辑的配置文件中加载。</p>
</div>
<div class="section" id="tut-weak-references">
<span id="id6"></span><h2>11.6. 弱引用<a class="headerlink" href="#tut-weak-references" title="Permalink to this headline">¶</a></h2>
<p>Python 自动进行内存管理（对大多数的对象进行引用计数和垃圾回收—— <em class="xref std std-term">garbage collection</em>  ——以循环利用）在最后一个引用消失后，内存会很快释放。</p>
<p>这个工作方式对大多数应用程序工作良好，但是偶尔会需要跟踪对象来做一些事。不幸的是，仅仅为跟踪它们创建引用也会使其长期存在。 <tt class="xref py py-mod docutils literal"><span class="pre">weakref</span></tt> 模块提供了不用创建引用的跟踪对象工具，一旦对象不再存在，它自动从弱引用表上删除并触发回调。典型的应用包括捕获难以构造的对象:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span> <span class="nn">weakref</span><span class="o">,</span> <span class="nn">gc</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">class</span> <span class="nc">A</span><span class="p">:</span>
<span class="gp">... </span>    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">value</span><span class="p">):</span>
<span class="gp">... </span>            <span class="bp">self</span><span class="o">.</span><span class="n">value</span> <span class="o">=</span> <span class="n">value</span>
<span class="gp">... </span>    <span class="k">def</span> <span class="nf">__repr__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="gp">... </span>            <span class="k">return</span> <span class="nb">str</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">value</span><span class="p">)</span>
<span class="gp">...</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">a</span> <span class="o">=</span> <span class="n">A</span><span class="p">(</span><span class="mi">10</span><span class="p">)</span>                   <span class="c"># create a reference</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">d</span> <span class="o">=</span> <span class="n">weakref</span><span class="o">.</span><span class="n">WeakValueDictionary</span><span class="p">()</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">d</span><span class="p">[</span><span class="s">&#39;primary&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">a</span>            <span class="c"># does not create a reference</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">d</span><span class="p">[</span><span class="s">&#39;primary&#39;</span><span class="p">]</span>                <span class="c"># fetch the object if it is still alive</span>
<span class="go">10</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">del</span> <span class="n">a</span>                       <span class="c"># remove the one reference</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">gc</span><span class="o">.</span><span class="n">collect</span><span class="p">()</span>                <span class="c"># run garbage collection right away</span>
<span class="go">0</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">d</span><span class="p">[</span><span class="s">&#39;primary&#39;</span><span class="p">]</span>                <span class="c"># entry was automatically removed</span>
<span class="gt">Traceback (most recent call last):</span>
  File <span class="nb">&quot;&lt;stdin&gt;&quot;</span>, line <span class="m">1</span>, in <span class="n">&lt;module&gt;</span>
    <span class="n">d</span><span class="p">[</span><span class="s">&#39;primary&#39;</span><span class="p">]</span>                <span class="c"># entry was automatically removed</span>
  File <span class="nb">&quot;C:/python33/lib/weakref.py&quot;</span>, line <span class="m">46</span>, in <span class="n">__getitem__</span>
    <span class="n">o</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">data</span><span class="p">[</span><span class="n">key</span><span class="p">]()</span>
<span class="gr">KeyError</span>: <span class="n">&#39;primary&#39;</span>
</pre></div>
</div>
</div>
<div class="section" id="tut-list-tools">
<span id="id7"></span><h2>11.7. 列表工具<a class="headerlink" href="#tut-list-tools" title="Permalink to this headline">¶</a></h2>
<p>很多数据结构可能会用到内置列表类型。然而，有时可能需要不同性能代价的实现。</p>
<p><tt class="xref py py-mod docutils literal"><span class="pre">array</span></tt> 模块提供了一个类似列表的 <tt class="xref py py-class docutils literal"><span class="pre">array()</span></tt> 对象，它仅仅是存储数据，更为紧凑。以下的示例演示了一个存储双字节无符号整数的数组（类型编码 <tt class="docutils literal"><span class="pre">&quot;H&quot;</span></tt> ）而非存储 16 字节 Python 整数对象的普通正规列表:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">array</span> <span class="kn">import</span> <span class="n">array</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">a</span> <span class="o">=</span> <span class="n">array</span><span class="p">(</span><span class="s">&#39;H&#39;</span><span class="p">,</span> <span class="p">[</span><span class="mi">4000</span><span class="p">,</span> <span class="mi">10</span><span class="p">,</span> <span class="mi">700</span><span class="p">,</span> <span class="mi">22222</span><span class="p">])</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">sum</span><span class="p">(</span><span class="n">a</span><span class="p">)</span>
<span class="go">26932</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">a</span><span class="p">[</span><span class="mi">1</span><span class="p">:</span><span class="mi">3</span><span class="p">]</span>
<span class="go">array(&#39;H&#39;, [10, 700])</span>
</pre></div>
</div>
<p><tt class="xref py py-mod docutils literal"><span class="pre">collections</span></tt> 模块提供了类似列表的 <tt class="xref py py-class docutils literal"><span class="pre">deque()</span></tt> 对象，它从左边添加（append）和弹出（pop）更快，但是在内部查询更慢。这些对象更适用于队列实现和广度优先的树搜索:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">collections</span> <span class="kn">import</span> <span class="n">deque</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">d</span> <span class="o">=</span> <span class="n">deque</span><span class="p">([</span><span class="s">&quot;task1&quot;</span><span class="p">,</span> <span class="s">&quot;task2&quot;</span><span class="p">,</span> <span class="s">&quot;task3&quot;</span><span class="p">])</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">d</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s">&quot;task4&quot;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">print</span><span class="p">(</span><span class="s">&quot;Handling&quot;</span><span class="p">,</span> <span class="n">d</span><span class="o">.</span><span class="n">popleft</span><span class="p">())</span>
<span class="go">Handling task1</span>

<span class="go">unsearched = deque([starting_node])</span>
<span class="go">def breadth_first_search(unsearched):</span>
<span class="go">    node = unsearched.popleft()</span>
<span class="go">    for m in gen_moves(node):</span>
<span class="go">        if is_goal(m):</span>
<span class="go">            return m</span>
<span class="go">        unsearched.append(m)</span>
</pre></div>
</div>
<p>除了链表的替代实现，该库还提供了 <tt class="xref py py-mod docutils literal"><span class="pre">bisect</span></tt> 这样的模块以操作存储链表:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span> <span class="nn">bisect</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">scores</span> <span class="o">=</span> <span class="p">[(</span><span class="mi">100</span><span class="p">,</span> <span class="s">&#39;perl&#39;</span><span class="p">),</span> <span class="p">(</span><span class="mi">200</span><span class="p">,</span> <span class="s">&#39;tcl&#39;</span><span class="p">),</span> <span class="p">(</span><span class="mi">400</span><span class="p">,</span> <span class="s">&#39;lua&#39;</span><span class="p">),</span> <span class="p">(</span><span class="mi">500</span><span class="p">,</span> <span class="s">&#39;python&#39;</span><span class="p">)]</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">bisect</span><span class="o">.</span><span class="n">insort</span><span class="p">(</span><span class="n">scores</span><span class="p">,</span> <span class="p">(</span><span class="mi">300</span><span class="p">,</span> <span class="s">&#39;ruby&#39;</span><span class="p">))</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">scores</span>
<span class="go">[(100, &#39;perl&#39;), (200, &#39;tcl&#39;), (300, &#39;ruby&#39;), (400, &#39;lua&#39;), (500, &#39;python&#39;)]</span>
</pre></div>
</div>
<p><tt class="xref py py-mod docutils literal"><span class="pre">heapq</span></tt> 提供了基于正规链表的堆实现。最小的值总是保持在 0 点。这在希望循环访问最小元素但是不想执行完整堆排序的时候非常有用:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">heapq</span> <span class="kn">import</span> <span class="n">heapify</span><span class="p">,</span> <span class="n">heappop</span><span class="p">,</span> <span class="n">heappush</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">data</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">7</span><span class="p">,</span> <span class="mi">9</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">6</span><span class="p">,</span> <span class="mi">8</span><span class="p">,</span> <span class="mi">0</span><span class="p">]</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">heapify</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>                      <span class="c"># rearrange the list into heap order</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">heappush</span><span class="p">(</span><span class="n">data</span><span class="p">,</span> <span class="o">-</span><span class="mi">5</span><span class="p">)</span>                 <span class="c"># add a new entry</span>
<span class="gp">&gt;&gt;&gt; </span><span class="p">[</span><span class="n">heappop</span><span class="p">(</span><span class="n">data</span><span class="p">)</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">3</span><span class="p">)]</span>  <span class="c"># fetch the three smallest entries</span>
<span class="go">[-5, 0, 1]</span>
</pre></div>
</div>
</div>
<div class="section" id="tut-decimal-fp">
<span id="id8"></span><h2>11.8. 十进制浮点数算法<a class="headerlink" href="#tut-decimal-fp" title="Permalink to this headline">¶</a></h2>
<p><tt class="xref py py-mod docutils literal"><span class="pre">decimal</span></tt> 模块提供了一个 <tt class="xref py py-class docutils literal"><span class="pre">Decimal</span></tt> 数据类型用于浮点数计算。相比内置的二进制浮点数实现 <tt class="xref py py-class docutils literal"><span class="pre">float</span></tt> ，这个类型有助于</p>
<ul class="simple">
<li>金融应用和其它需要精确十进制表达的场合，</li>
<li>控制精度，</li>
<li>控制舍入以适应法律或者规定要求，</li>
<li>确保十进制数位精度，或者</li>
<li>用户希望计算结果与手算相符的场合。</li>
</ul>
<p>例如，计算 70 分电话费的 5% 税计算，十进制浮点数和二进制浮点数计算结果的差别如下。如果在分值上舍入，这个差别就很重要了:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">decimal</span> <span class="kn">import</span> <span class="o">*</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">round</span><span class="p">(</span><span class="n">Decimal</span><span class="p">(</span><span class="s">&#39;0.70&#39;</span><span class="p">)</span> <span class="o">*</span> <span class="n">Decimal</span><span class="p">(</span><span class="s">&#39;1.05&#39;</span><span class="p">),</span> <span class="mi">2</span><span class="p">)</span>
<span class="go">Decimal(&#39;0.74&#39;)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">round</span><span class="p">(</span><span class="o">.</span><span class="mi">70</span> <span class="o">*</span> <span class="mf">1.05</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span>
<span class="go">0.73</span>
</pre></div>
</div>
<p><tt class="xref py py-class docutils literal"><span class="pre">Decimal</span></tt> 的结果总是保有结尾的 0，自动从两位精度延伸到4位。 Decimal 重现了手工的数学运算，这就确保了二进制浮点数无法精确保有的数据精度。</p>
<p>高精度使 <tt class="xref py py-class docutils literal"><span class="pre">Decimal</span></tt> 可以执行二进制浮点数无法进行的模运算和等值测试:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">Decimal</span><span class="p">(</span><span class="s">&#39;1.00&#39;</span><span class="p">)</span> <span class="o">%</span> <span class="n">Decimal</span><span class="p">(</span><span class="s">&#39;.10&#39;</span><span class="p">)</span>
<span class="go">Decimal(&#39;0.00&#39;)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="mf">1.00</span> <span class="o">%</span> <span class="mf">0.10</span>
<span class="go">0.09999999999999995</span>

<span class="gp">&gt;&gt;&gt; </span><span class="nb">sum</span><span class="p">([</span><span class="n">Decimal</span><span class="p">(</span><span class="s">&#39;0.1&#39;</span><span class="p">)]</span><span class="o">*</span><span class="mi">10</span><span class="p">)</span> <span class="o">==</span> <span class="n">Decimal</span><span class="p">(</span><span class="s">&#39;1.0&#39;</span><span class="p">)</span>
<span class="go">True</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">sum</span><span class="p">([</span><span class="mf">0.1</span><span class="p">]</span><span class="o">*</span><span class="mi">10</span><span class="p">)</span> <span class="o">==</span> <span class="mf">1.0</span>
<span class="go">False</span>
</pre></div>
</div>
<p><tt class="xref py py-mod docutils literal"><span class="pre">decimal</span></tt> 提供了必须的高精度算法:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">getcontext</span><span class="p">()</span><span class="o">.</span><span class="n">prec</span> <span class="o">=</span> <span class="mi">36</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">Decimal</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> <span class="o">/</span> <span class="n">Decimal</span><span class="p">(</span><span class="mi">7</span><span class="p">)</span>
<span class="go">Decimal(&#39;0.142857142857142857142857142857142857&#39;)</span>
</pre></div>
</div>
</div>
</div>


          </div>
        </div>
      </div>
      <div class="sphinxsidebar">
        <div class="sphinxsidebarwrapper">
  <h3><a href="index.html">Table Of Contents</a></h3>
  <ul>
<li><a class="reference internal" href="#">11. 标准库浏览 &#8211; Part II</a><ul>
<li><a class="reference internal" href="#tut-output-formatting">11.1. 输出格式</a></li>
<li><a class="reference internal" href="#tut-templating">11.2. 模板</a></li>
<li><a class="reference internal" href="#tut-binary-formats">11.3. 使用二进制数据记录布局</a></li>
<li><a class="reference internal" href="#tut-multi-threading">11.4. 多线程</a></li>
<li><a class="reference internal" href="#tut-logging">11.5. 日志</a></li>
<li><a class="reference internal" href="#tut-weak-references">11.6. 弱引用</a></li>
<li><a class="reference internal" href="#tut-list-tools">11.7. 列表工具</a></li>
<li><a class="reference internal" href="#tut-decimal-fp">11.8. 十进制浮点数算法</a></li>
</ul>
</li>
</ul>

  <h4>Previous topic</h4>
  <p class="topless"><a href="stdlib.html"
                        title="previous chapter">10. Python 标准库概览</a></p>
  <h4>Next topic</h4>
  <p class="topless"><a href="whatnow.html"
                        title="next chapter">12. 接下来？</a></p>
  <h3>This Page</h3>
  <ul class="this-page-menu">
    <li><a href="_sources/stdlib2.txt"
           rel="nofollow">Show Source</a></li>
  </ul>
<div id="searchbox" style="display: none">
  <h3>Quick search</h3>
    <form class="search" action="search.html" method="get">
      <input type="text" name="q" />
      <input type="submit" value="Go" />
      <input type="hidden" name="check_keywords" value="yes" />
      <input type="hidden" name="area" value="default" />
    </form>
    <p class="searchtip" style="font-size: 90%">
    Enter search terms or a module, class or function name.
    </p>
</div>
<script type="text/javascript">$('#searchbox').show(0);</script>
        </div>
      </div>
      <div class="clearer"></div>
    </div>
    <div class="related">
      <h3>Navigation</h3>
      <ul>
        <li class="right" style="margin-right: 10px">
          <a href="genindex.html" title="General Index"
             >index</a></li>
        <li class="right" >
          <a href="whatnow.html" title="12. 接下来？"
             >next</a> |</li>
        <li class="right" >
          <a href="stdlib.html" title="10. Python 标准库概览"
             >previous</a> |</li>
        <li><a href="index.html">Python tutorial 3.4 documentation</a> &raquo;</li> 
      </ul>
    </div>
    <div class="footer">
        &copy; Copyright 2013, D.D.
      Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.2.1.
    </div>
  </body>
</html>